#include <crt_util.h>

void varaint_t_init(varaint_t* src)
{
    rc_return(src != NULL);
    s_memset(src, 0, sizeof(varaint_t));
}

int varaint_t_malloc_string(varaint_t* src, ULONG size, LPCSTR dst)
{
    rc_error(src != NULL, S_ERROR);
    varaint_t_free_string(src);
    varaint_t_init(src);
    src->vt = VET_LPSTR;
    src->pszVal = (char*)calloc(size, sizeof(char));
    rc_error(src->pszVal != NULL, S_ERROR);
    src->len = size;
    return varaint_t_copystring(src, size, dst);
}
int varaint_t_malloc_wstring(varaint_t* src, ULONG size, LPCWSTR dst)
{
    rc_error(src != NULL, S_ERROR);
    varaint_t_free_string(src);
    varaint_t_init(src);
    src->vt = VET_LPWSTR;
    src->pwszVal = (wchar_t*)calloc(size, sizeof(wchar_t));
    rc_error(src->pwszVal != NULL, S_ERROR);
    src->len = size;

    return varaint_t_copywstring(src, size, dst);
}

int varaint_t_free_string(varaint_t* src)
{
    rc_error(src != NULL, S_ERROR);
    rc_error(((src->vt >= VET_LPSTR) && (VET_LPWSTR <= src->vt)), S_ERROR);
    switch (src->vt) {
    case VET_LPSTR:
        free(src->pszVal);
        break;
    case VET_LPWSTR:
        free(src->pszVal);
        break;
    default:
        goto end;
        break;
    }
    return S_SUCCESS;
end:
    return S_ERROR;
}

int varaint_t_copy(varaint_t* src, const varaint_t* dst)
{
    rc_error(src != NULL, S_ERROR);
    rc_error(dst != NULL, S_ERROR);

    switch (dst->vt) {
    case VET_I1:
        src->cVal = dst->cVal;
        break;
    case VET_I2:
        src->iVal = dst->iVal;
        break;
    case VET_I4:
        src->lVal = dst->lVal;
        break;
    case VET_I8:
        src->llVal = dst->llVal;
        break;
    case VET_UI1:
        src->uVal = dst->uVal;
        break;
    case VET_UI2:
        src->uiVal = dst->uiVal;
        break;
    case VET_UI4:
        src->ulVal = dst->ulVal;
        break;
    case VET_UI8:
        src->ullVal = dst->ullVal;
        break;
    case VET_R4:
        src->fltVal = dst->fltVal;
        break;
    case VET_R8:
        src->dblVal = dst->dblVal;
        break;
    case VET_INT:
        src->intVal = dst->intVal;
        break;
    case VET_UINT:
        src->uintVal = dst->uintVal;
        break;
    case VET_LPSTR:
        src->pszVal = dst->pszVal;
        break;
    case VET_LPWSTR:
        src->pwszVal = dst->pwszVal;
        break;
    case VET_VOID:
        src->pVal = dst->pVal;
        break;
    default:
        goto end;
        break;
    }

    src->vt = dst->vt;
    return S_SUCCESS;
end:
    return S_ERROR;
}

int varaint_t_copystring(varaint_t* src, ULONG size, LPCSTR dst)
{
    rc_error(src != NULL, S_ERROR);
    rc_error(src->vt == VET_LPSTR, S_ERROR);
    s_strcpy(src->pszVal, src->len, dst);
    return S_SUCCESS;
}
int varaint_t_copywstring(varaint_t* src, ULONG size, LPCWSTR dst)
{
    rc_error(src != NULL, S_ERROR);
    rc_error(src->vt == VET_LPWSTR, S_ERROR);
    s_wstrcpy(src->pwszVal, src->len, dst);
    return S_SUCCESS;
}
